/**
***********************************************************************
*
* Copyright 2011 Stefan Wöhle
*
* This file is part of PixelMath
*
* PixelMath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PixelMath is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PixelMath. If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************
*/

#include "formulaeditor.h"
#include "ui_formulaeditor.h"
#include "pixelmathwindow.h"
#include "formulawidget.h"
#include "emptyformulawidget.h"
#include "constantwidget.h"
#include "formulaexception.h"
#include <QMessageBox>

/**********************************************************
 *
 *  public
 *
 **********************************************************/
FormulaEditor::FormulaEditor(PixelMathWindow *owner) :
    QMainWindow(owner),
    ui(new Ui::FormulaEditor)
{
    this->owner = owner;
    ui->setupUi(this);

    EmptyFormulaWidget *empty;
    empty = new EmptyFormulaWidget(this);
    connect(empty, SIGNAL(formulaChoosen(FormulaWidget*)),
            this, SLOT(formulaAnchorChoosen(FormulaWidget*)));
    redFW = empty;
    ui->gridLayout->addWidget(redFW, 0, 1);

    empty = new EmptyFormulaWidget(this);
    connect(empty, SIGNAL(formulaChoosen(FormulaWidget*)),
            this, SLOT(formulaAnchorChoosen(FormulaWidget*)));
    greenFW = empty;
    ui->gridLayout->addWidget(greenFW, 1, 1);

    empty = new EmptyFormulaWidget(this);
    connect(empty, SIGNAL(formulaChoosen(FormulaWidget*)),
            this, SLOT(formulaAnchorChoosen(FormulaWidget*)));
    blueFW = empty;
    ui->gridLayout->addWidget(blueFW, 2, 1);
}

FormulaEditor::~FormulaEditor()
{
    if (redFW) delete redFW;
    if (greenFW) delete greenFW;
    if (blueFW) delete blueFW;
    delete ui;
}

/**********************************************************
 *
 *  public
 *
 **********************************************************/
void FormulaEditor::cutColorValue(int &c)
{
    if (c > 255) {
        c = 255;
    }
    else if (c < 0) {
        c = 0;
    }
}

/**********************************************************
 *
 *  GUI "event"-handling
 *
 **********************************************************/
void FormulaEditor::on_applyButton_clicked()
{
    // get the original image and create a full copy for the modified image
    QImage modifiedImage = owner->originalImage().copy();
    if (!modifiedImage.isNull())
    {
        if (redFW->metaObject()->className() == QString("EmptyFormulaWidget")
                || greenFW->metaObject()->className() == QString("EmptyFormulaWidget")
                || blueFW->metaObject()->className() == QString("EmptyFormulaWidget"))
        {
            QMessageBox::warning(this, tr("No formula"),
                                 tr("At least one formula\n" \
                                    "was not defined"));
            return;
        }
        Formula::setSourceImage(owner->originalImage());
        try {
            int x, y;
            int red, green, blue;
            for(x = 0; x < modifiedImage.width(); x++)
            {
                for(y = 0; y < modifiedImage.height(); y++)
                {
                    // calculate resulting color values
                    red = (int)redFW->formulaElement().value(x, y);
                    green = (int)greenFW->formulaElement().value(x, y);
                    blue = (int)blueFW->formulaElement().value(x,y);

                    // cut them if they exceed the borders
                    cutColorValue(red);
                    cutColorValue(green);
                    cutColorValue(blue);

                    // write them to the corresponding pixel
                    modifiedImage.setPixel(x, y, qRgb(red, green, blue));
                }
            }

            owner->setModifiedImage(modifiedImage);
        }
        catch (FormulaException e)
        {
            QMessageBox::warning(this,
                                 tr("Exception occured"),
                                 e.getMsg());
        }
    }
    else
    {
        QMessageBox::warning(this, tr("No image"),
                             tr("Please load image before\n" \
                                "applying formula."));
    }
}

void FormulaEditor::on_actionClose_triggered()
{
    this->close();
}

void FormulaEditor::formulaAnchorChoosen(FormulaWidget *formulaWidget)
{
    FormulaWidget* source = (FormulaWidget*)sender();
    ui->gridLayout->removeWidget(source);
    source->hide();
    if (source == redFW)
    {
        redFW = formulaWidget;
        connect(formulaWidget, SIGNAL(destroyed(QObject*)),
                this, SLOT(replaceSubwidget(QObject*)));
        ui->gridLayout->addWidget(redFW, 0, 1);
    }
    else if (source == greenFW)
    {
        greenFW = formulaWidget;
        connect(formulaWidget, SIGNAL(destroyed(QObject*)),
                this, SLOT(replaceSubwidget(QObject*)));
        ui->gridLayout->addWidget(greenFW, 1, 1);
    }
    else if (source == blueFW)
    {
        blueFW = formulaWidget;
        connect(formulaWidget, SIGNAL(destroyed(QObject*)),
                this, SLOT(replaceSubwidget(QObject*)));
        ui->gridLayout->addWidget(blueFW, 2, 1);
    }
}

void FormulaEditor::replaceSubwidget(QObject *destroyed)
{

    EmptyFormulaWidget *empty;
    empty = new EmptyFormulaWidget(this);
    connect(empty, SIGNAL(formulaChoosen(FormulaWidget*)),
            this, SLOT(formulaAnchorChoosen(FormulaWidget*)));

    if (destroyed == redFW)
    {
        redFW = empty;
        ui->gridLayout->addWidget(redFW, 0, 1);
    }
    else if (destroyed == greenFW)
    {
        greenFW = empty;
        ui->gridLayout->addWidget(greenFW, 1, 1);
    }
    else if (destroyed == blueFW)
    {
        blueFW = empty;
        ui->gridLayout->addWidget(blueFW, 2, 1);
    }
}
